package cn.demo.service.impl;

import cn.demo.entity.Account;
import cn.demo.mapper.AccountMapper;
import cn.demo.service.RetryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class RetryServiceImpl implements RetryService {
    @Autowired
    private AccountMapper accountMapper;

    /**
     * @Retryable：标记当前方法会使用重试机制
     * value:充实的出发机制，当遇到Exception异常的时候，会触发充实
     * maxAttempts:最大重试次数，包括第一次执行
     * delay：重试的间隔时间
     * multiplier：delay时间的间隔倍数
     * maxDelay：重试次数之间的最大时间间隔，默认为0，如果小于delay的设置，则默认为30000L
     * @param fromAccountId
     * @param toAccountId
     * @param money
     * @throws Exception
     */
    @Transactional
    @Retryable(value = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 300,multiplier = 1,maxDelay = 10000))
    @Override
    public void retryTransferAccounts(int fromAccountId, int toAccountId, int money) throws Exception {
        //扣款
        Account fromAccount = accountMapper.selectById(fromAccountId);
        fromAccount.setBalance(fromAccount.getBalance()-money);
        accountMapper.updateById(fromAccount);

        int a = 2 / 0;
        //加款
        Account toAccount = accountMapper.selectById(toAccountId);
        toAccount.setBalance(fromAccount.getBalance()+money);
        accountMapper.updateById(toAccount);
        throw new Exception();
    }

    /**
     * @Recover：标记方法为回调方法，传参与@Retryable的value值需一致
     * @param e
     */
    @Recover
    public void recover(Exception e){
        System.out.println("回调方法执行");
    }
}
